#include "eobd.h"
#include "stdcan.h"

CanTxMsg mEobdCheckEng =
{
    0x7df, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x02, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00
};

CanTxMsg mEobdStream =
{
    0x7df, 0x18db33f1,
    CAN_ID_STD, CAN_RTR_DATA,
    8,
    0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


EobdPidMap mEobdPidMap[ENG_DATA_SIZE] =
{
    { ENG_DATA_RPM,           0x0c, 1, 2, SUPPORTED },
    { ENG_DATA_VS,            0x0d, 1, 1, SUPPORTED },
    { ENG_DATA_ECT,           0x05, 1, 1, SUPPORTED },
    { ENG_DATA_IAT,           0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_APP,           0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_TP,            0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_ERT,           0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_LOAD,          0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_BATTVOLT,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_REALFUELCO,    0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_FUELLEVEL,     0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_ODO,           0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_LTFT,          0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_STFT,          0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE1,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE2,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE3,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE4,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE5,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_MISFIRE6,      0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_FCLS,          0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_KEYSTATUS,     0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_HO2S1,         0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_HO2S2,         0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_MAP,           0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_INJECTPULSE,   0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_OILPRESSURE,   0x00, 1, 1, UNSUPPORTED },
    { ENG_DATA_OILLEVELSTATUS,0x00, 1, 1, UNSUPPORTED },
};

VehicleCtrlOps mCtrlOps;
VehicleProcessOps mProcessOps;

void eobd_init(Vehicle *vehicle)
{
    logi("%s", __func__);
    mCtrlOps.support |= SUPPORT_CONTROL_WINDOW;
    mCtrlOps.support |= SUPPORT_CONTROL_DOOR;
    mCtrlOps.control_window = eobd_control_window;
    mCtrlOps.control_door = eobd_control_door;
    mProcessOps.check_engine_on = eobd_check_engine_on;
    mProcessOps.get_rpm = eobd_get_rpm;
    mProcessOps.process_eng_data = eobd_process_eng_data;
    mProcessOps.get_fault_code = eobd_get_fault_code;

    vehicle->ctrlOps = &mCtrlOps;
    vehicle->processOps = &mProcessOps;

    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
}

//eobd control functions
void eobd_control_window(uint8_t state)
{
    logi("%s: state = %d", __func__, state);
}

void eobd_control_door(uint8_t state)
{
    logi("%s: state = %d", __func__, state);
}

//eobd data functions
uint8_t eobd_check_engine_on(void)
{
    uint8_t on = FALSE;
    StdCanData *data;

    data = (StdCanData *)malloc(sizeof(StdCanData));
    memset(data, 0x00, sizeof(StdCanData));
    data->tx_id = 0x7df;
    data->cmd_len = 0x02;
    data->cmd = 0x01;
    data->id = 0x0c;
    data->rx_id = 0x7e8;
    if(StdCan_ioctl(data)) {
        on = TRUE;
    } else {
        loge("%s: failed", __func__);
        on = FALSE;
    }
    free(data);

    return TRUE;
}

void eobd_get_rpm(uint16_t *rpm)
{
    StdCanData *data;

    data = (StdCanData *)malloc(sizeof(StdCanData));
    memset(data, 0x00, sizeof(StdCanData));
    data->tx_id = 0x7df;
    data->cmd_len = 0x02;
    data->cmd = 0x01;
    data->id = 0x0c;
    data->rx_id = 0x7e8;
    if(StdCan_ioctl(data)) {
        *rpm = (data->rx_data[1] << 8) | data->rx_data[2];
    } else {
        loge("%s: failed", __func__);
        *rpm = 0;
    }
    free(data);
}

void eobd_process_eng_data(EngineDataMap *dataMap)
{
    uint8_t i;
    uint8_t support;
    uint8_t pid;
    uint8_t offset;
    uint8_t size;
    StdCanData *data;

//    uint8_t fake_data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    for(i = 0; i < ENG_DATA_SIZE; i++) {
        support = mEobdPidMap[i].support;
        //check wether this id is supported?
        if(support == UNSUPPORTED)
            continue;
        pid = mEobdPidMap[i].pid;
        offset = mEobdPidMap[i].offset;
        size = mEobdPidMap[i].size;
#if 0
        //add fake code
        dataMap->data[i].id = i;
        dataMap->data[i].updated = TRUE;
        dataMap->data[i].len = size;
        memcpy(dataMap->data[i].data, fake_data + offset, size);
#endif

        data = (StdCanData *)malloc(sizeof(StdCanData));
        memset(data, 0x00, sizeof(StdCanData));
        data->tx_id = 0x7df;
        data->cmd_len = 0x02;
        data->cmd = 0x01;
        data->id = pid;
        data->rx_id = 0x7e8;

        //send stream msg
        if(StdCan_ioctl(data)) {
            dataMap->data[i].id = i;
            dataMap->data[i].updated = TRUE;
            dataMap->data[i].len = size;
            memcpy(dataMap->data[i].data, data->rx_data + offset, size);
        }
        free(data);
    }
}

void eobd_get_fault_code(uint8_t type, FaultCodeItem *item)
{
    logi("%s: type = %d", __func__, type);
}

void eobd_check_support(void)
{
    CanRxMsg rxMsg;
    CanTxMsg mEobdCheckEng =
    {
        0x7df, 0x18db33f1,
        CAN_ID_STD, CAN_RTR_DATA,
        8,
        0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    bsp_can_filter(0x7e8, 0x7e8, 0x7ff, 0x7ff);
    if(vehicle_can_session(&mEobdCheckEng, &rxMsg)) {
    } else {
    }
}
